﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;

namespace LIK.NetAssemblyChecker
{
    public partial class frmMain : Form
    {

        #region Private members

        int _intNetCounter = 0;

        #endregion


        #region Constructor
        public frmMain()
        {
            InitializeComponent();
            cmbInputFolder.Text = Properties.Settings.Default.LastusedFolder;
            RepopulateMRUCmb();
        }
        #endregion


        #region Form Events

        private void tsbtnTogglePropertyPage_Click(object sender, EventArgs e)
        {
            tsbtnTogglePropertyPage.Checked = !tsbtnTogglePropertyPage.Checked;
            pgSelectedFile.Visible = splitterLeft.Visible = tsbtnTogglePropertyPage.Checked;
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            if(cmbInputFolder.Text.Length>0)
                fbd.SelectedPath = cmbInputFolder.Text;
            if (DialogResult.OK == fbd.ShowDialog(this))
            {
                cmbInputFolder.Text = fbd.SelectedPath;
            }
        }

        private void btnCheck_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(cmbInputFolder.Text))
            {
                Properties.Settings.Default.LastusedFolder = cmbInputFolder.Text;
                if (!Properties.Settings.Default.MRUFiles.Contains(cmbInputFolder.Text))
                {
                    Properties.Settings.Default.MRUFiles.Insert(0, cmbInputFolder.Text);
                    if (Properties.Settings.Default.MRUFiles.Count > 10)
                        Properties.Settings.Default.MRUFiles.RemoveAt(10);
                    RepopulateMRUCmb();
                }
                Properties.Settings.Default.Save();
                //clean up all objects
                trvDependant.Nodes.Clear();
                Commons.AssemblyDependants.Clear();
                Commons.RunTimeVersions.Clear();
                trvFiles.Nodes.Clear();
                trvNetVersions.Nodes.Clear();
                pgSelectedFile.SelectedObject = null;
                _intNetCounter = 0;
                lblInfo.Text = "";
                Commons.FolderToCheck = cmbInputFolder.Text;
                //collect information about selected files
                CheckFolder(null, new DirectoryInfo(cmbInputFolder.Text));
                //display found data
                lblInfo.Text = String.Format("Found {0} NET Files", _intNetCounter);
                for (int i = 0; i < Commons.RunTimeVersions.Count; i++)
                {
                    trvNetVersions.Nodes.Add(Commons.RunTimeVersions[i]);
                }
                Commons.AssemblyDependants.Sort();
                for (int i = 0; i < Commons.AssemblyDependants.Count; i++)
                {
                    trvDependant.Nodes.Add(Commons.AssemblyDependants[i]);
                }
            }
            else
            {
                cmbInputFolder.Select();
                cmbInputFolder.SelectionStart = 0;
                cmbInputFolder.SelectionLength = cmbInputFolder.Text.Length;
            }
        }

        private void trvFiles_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (trvFiles.SelectedNode == null)
                pgSelectedFile.SelectedObject = null;
            else
                pgSelectedFile.SelectedObject = trvFiles.SelectedNode.Tag;
        }

        private void trvNetVersions_DoubleClick(object sender, EventArgs e)
        {
            if (trvNetVersions.SelectedNode == null)
                return;
            string s = trvNetVersions.SelectedNode.Text;
            HighlightInTreeView(s);
        }

        private void trvDependant_DoubleClick(object sender, EventArgs e)
        {
            if (trvDependant.SelectedNode == null)
                return;
            string s = trvDependant.SelectedNode.Text;
            HighlightInTreeView(s);
        }

        private void trvFiles_DoubleClick(object sender, EventArgs e)
        {
            if (trvFiles.SelectedNode == null)
                return;
            if (trvFiles.SelectedNode.SelectedImageIndex == 0)
                return;
            string s = trvFiles.SelectedNode.Text;
            HighlightInTreeView(s);
        }

        #endregion


        #region Methods
        void CheckFolder(TreeNode parent, DirectoryInfo di)
        {
            if (chckbCheckNestedFiles.Checked)
            {
                DirectoryInfo[] dirs = di.GetDirectories();
                for (int i = 0; i < dirs.Length; i++)
                {
                    DirectoryInfo din = dirs[i];
                    TreeNode ftn = new TreeNode(din.Name);
                    ftn.ImageIndex = 0;
                    ftn.SelectedImageIndex = 0;
                    ftn.StateImageIndex = 0;

                    if (parent != null)
                        parent.Nodes.Add(ftn);
                    CheckFolder(ftn, din);
                }
            }
            FileInfo[] fis = di.GetFiles("*.exe", SearchOption.TopDirectoryOnly);
            CheckFiles(fis, parent);
            fis = di.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
            CheckFiles(fis, parent);
        }

        void CheckFiles(FileInfo[] fis, TreeNode parent)
        {
            for (int i = 0; i < fis.Length; i++)
            {
                if (parent != null && parent.TreeView == null)
                {
                    //find top
                    TreeNode pr = parent;
                    while (pr.Parent != null)
                    {
                        pr = pr.Parent;
                    }
                    trvFiles.Nodes.Add(pr);
                }
                FileInfo fi = fis[i];
                CheckFile(parent, fi.FullName);
            }
        }


        private void CheckFile(TreeNode parent, string file)
        {
            TreeNode dllTreeNode = null;
            try
            {
                NetAssembly nf = new NetAssembly(file);
                dllTreeNode = nf.GetTreeNode(chckbShowDependant.Checked);
            }
            catch
            {
                SystemAssembly uf = new SystemAssembly(file);
                dllTreeNode = uf.GetTreeNode();
            }

            _intNetCounter++;

            if (parent != null)
                parent.Nodes.Add(dllTreeNode);
            else
                trvFiles.Nodes.Add(dllTreeNode);
        }

        void HighlightInTreeView(string s)
        {
            trvFiles.CollapseAll();
            foreach (TreeNode t in trvFiles.Nodes)
            {
                if(t.Text.Contains( s))
                {   
                    t.BackColor = Color.LightGray;
                    TreeNode p = t.Parent;
                    while (p != null)
                    {
                        p.Expand();
                        p = p.Parent;
                    }
                }
                else
                    t.BackColor = Color.FromKnownColor(KnownColor.Window);
                CheckNodesFor(t, s);
            }
        }

        void CheckNodesFor(TreeNode tp, string s)
        {
            foreach (TreeNode t in tp.Nodes)
            {
                if(t.Text.Contains( s))
                {   
                    t.BackColor = Color.Gray;
                    TreeNode p = t.Parent;
                    while (p != null)
                    {
                        p.Expand();
                        p = p.Parent;
                    }
                }
                else
                    t.BackColor = Color.FromKnownColor(KnownColor.Window);
                CheckNodesFor(t, s);
            }
        }

        #endregion

        private void RepopulateMRUCmb()
        {
            cmbInputFolder.Items.Clear();
            if (Properties.Settings.Default.MRUFiles == null)
                Properties.Settings.Default.MRUFiles = new System.Collections.Specialized.StringCollection();
            string[] files = new string[Properties.Settings.Default.MRUFiles.Count];
            Properties.Settings.Default.MRUFiles.CopyTo(files, 0);
            cmbInputFolder.Items.AddRange(files);
        }

        frmAssemblyBrowser _AssemblyBrowser = null;
        private void tsmnuBrowseAssembly_Click(object sender, EventArgs e)
        {
            if (trvFiles.SelectedNode == null)
                return;
            if (_AssemblyBrowser == null)
            {
                _AssemblyBrowser = new frmAssemblyBrowser(trvFiles.SelectedNode.Tag);
                _AssemblyBrowser.FormClosing += new FormClosingEventHandler(_AssemblyBrowser_FormClosing);
                _AssemblyBrowser.Owner = this;
                _AssemblyBrowser.Show();
            }
        }

        void _AssemblyBrowser_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(_AssemblyBrowser != null)
            {
                _AssemblyBrowser.Dispose();
                _AssemblyBrowser = null;
            }
        }








    }
}